package com.android.htdvideoview;

import android.content.Context;
import android.graphics.Color;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.Surface;
import android.view.TextureView;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.sansecy.android.simplevideo.Player;
import com.sansecy.android.simplevideo.VideoTextureView;

import java.io.IOException;

import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;

/**
 * 项目名称：VideoTest
 * 类 名 称：IjkVideoView
 * 类 描 述：IjkVideoView
 * 创建时间：2019-11-15 21:18
 * 创 建 人：sansecy
 */
public class IjkVideoView extends FrameLayout implements Player, TextureView.SurfaceTextureListener {
    private static final String TAG = "IjkVideoView-App";
    private OnPreparedListener mOnPreparedListener;
    private OnCompletionListener mOnCompletionListener;
    private OnBufferingUpdateListener mOnBufferingUpdateListener;
    private OnSeekCompleteListener mOnSeekCompleteListener;
    private OnVideoSizeChangedListener mOnVideoSizeChangedListener;
    private OnErrorListener mOnErrorListener;
    private OnInfoListener mOnInfoListener;

    private VideoTextureView mTargetView;
    private IjkMediaPlayer mPlayer;

    private Surface mSurface;
    private int mBufferingPercent = 0;
    private boolean mLooping = false;
    private String mUrl;
    private Uri mUri;

    public IjkVideoView(@NonNull Context context) {
        this(context, null);
    }

    public IjkVideoView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setBackgroundColor(Color.BLACK);
        mTargetView = new VideoTextureView(getContext());
        mTargetView.setSurfaceTextureListener(this);
        LayoutParams layoutParams = new LayoutParams(-1, -1);
        layoutParams.gravity = Gravity.CENTER;
        addView(mTargetView, layoutParams);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        Log.d(this.getClass().getSimpleName() + "-App", "onSurfaceTextureAvailable() called with: surface = [" + surface + "], width = [" + width + "], height = [" + height + "]");
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        Log.d(this.getClass().getSimpleName() + "-App", "onSurfaceTextureSizeChanged() called with: surface = [" + surface + "], width = [" + width + "], height = [" + height + "]");
        mSurface = new Surface(surface);
        if (mPlayer != null) {
            mPlayer.setSurface(mSurface);
        }
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        Log.d(this.getClass().getSimpleName() + "-App", "onSurfaceTextureDestroyed() called with: surface = [" + surface + "]");
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    }

    @Override
    public void start() {
        Log.d(this.getClass().getSimpleName() + "-App", "start() called");
        try {
            if (mPlayer != null) {
                mPlayer.start();
            }
        } catch (IllegalStateException e) {
            mErrorListener.onError(mPlayer, 0, 0);
        }
    }

    @Override
    public void pause() {
        Log.d(this.getClass().getSimpleName() + "-App", "pause() called");
        try {
            if (mPlayer != null) {
                mPlayer.pause();
            }
        } catch (IllegalStateException e) {
            mErrorListener.onError(mPlayer, 0, 0);
        }

    }

    @Override
    public int getDuration() {
        if (mPlayer != null) {
            return (int) mPlayer.getDuration();
        }
        return 0;
    }

    @Override
    public int getCurrentPosition() {
        if (mPlayer != null) {
            return (int) mPlayer.getCurrentPosition();
        }
        return 0;
    }

    @Override
    public void seekTo(int pos) {
        try {
            if (mPlayer != null) {
                mPlayer.seekTo(pos);
            }
        } catch (IllegalStateException e) {
            mErrorListener.onError(mPlayer, 0, 0);
        }
    }

    @Override
    public boolean isPlaying() {
        if (mPlayer != null) {
            return mPlayer.isPlaying();
        }
        return false;
    }

    @Override
    public int getBufferPercentage() {
        if (mPlayer != null) {
            return (int) mPlayer.getVideoCachedDuration();
        }
        return 0;
    }


    @Override
    public void loadUrl(String url) {
        mUrl = url;
        mUri = null;
    }

    @Override
    public void loadUri(Uri uri) {
        mUri = uri;
        mUrl = null;

    }

    @Override
    public void openVideo() {
        try {
            mPlayer = new IjkMediaPlayer();
            if (mUrl != null) {
                mPlayer.setDataSource(mUrl);
            }
            if (mUri != null) {
                mPlayer.setDataSource(getContext(), mUri);
            }
            mPlayer.setOnErrorListener(mErrorListener);
            mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mPlayer.setLooping(mLooping);
            mPlayer.setOnVideoSizeChangedListener(mVideoSizeChangedListener);
            mPlayer.setOnPreparedListener(mPreparedListener);
            mPlayer.setOnCompletionListener(mCompletionListener);
            mPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
            mPlayer.setOnErrorListener(mErrorListener);
            mPlayer.setOnInfoListener(mInfoListener);
            mPlayer.setSurface(mSurface);
            mPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
            mPlayer.setScreenOnWhilePlaying(true);
            mPlayer.prepareAsync();
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared",0);
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "reconnect", 1);
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"analyzeduration",1);
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzemaxduration", 100L);
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 10240L);
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1L);
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0L);
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1L);
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "fastseek");//设置seekTo能够快速seek到指定位置并播放
            mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"packet-buffering",1);
        } catch (IOException | IllegalArgumentException | SecurityException | IllegalStateException e) {
            Log.d(this.getClass().getSimpleName() + "-App", "openVideo() called  " + e.getMessage());
            mErrorListener.onError(mPlayer, 0, 0);
        }
    }

    @Override
    public void stopPlayback() {
        Log.d(this.getClass().getSimpleName() + "-App", "stopPlayback() called");
        try {
            if (mPlayer != null) {
                mPlayer.stop();
                mPlayer.release();
            }
        } catch (IllegalStateException e) {
            mErrorListener.onError(mPlayer, 0, 0);
        }

    }
    public void setLooping(boolean looping) {
        mLooping = looping;
        if (mPlayer != null) {
            mPlayer.setLooping(looping);
        }
    }

    private IMediaPlayer.OnPreparedListener mPreparedListener = new IMediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(IMediaPlayer mp) {
            if (mOnPreparedListener != null) {
                mOnPreparedListener.onPrepared();
            }
        }
    };
    private IMediaPlayer.OnCompletionListener mCompletionListener = new IMediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(IMediaPlayer mp) {
            if (mOnCompletionListener != null) {
                mOnCompletionListener.onCompletion();
            }
        }
    };
    private IMediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new IMediaPlayer.OnBufferingUpdateListener() {
        @Override
        public void onBufferingUpdate(IMediaPlayer mp, int percent) {
            if (mOnBufferingUpdateListener != null) {
                mOnBufferingUpdateListener.onBufferingUpdate(percent);
            }
        }
    };
    private IMediaPlayer.OnSeekCompleteListener mSeekCompleteListener = new IMediaPlayer.OnSeekCompleteListener() {
        @Override
        public void onSeekComplete(IMediaPlayer mp) {
            if (mOnSeekCompleteListener != null) {
                mOnSeekCompleteListener.onSeekComplete();
            }
        }
    };
    private IMediaPlayer.OnVideoSizeChangedListener mVideoSizeChangedListener = new IMediaPlayer.OnVideoSizeChangedListener() {
        @Override
        public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sar_num, int sar_den) {
            int videoWidth = mp.getVideoWidth();
            int videoHeight = mp.getVideoHeight();
            mTargetView.setVideoWidthHeight(videoWidth, videoHeight);
            if (videoWidth != 0 && videoHeight != 0) {
                mTargetView.requestLayout();
            }
            if (mOnVideoSizeChangedListener != null) {
                mOnVideoSizeChangedListener.onVideoSizeChanged(width, height);
            }
        }
    };
    private IMediaPlayer.OnErrorListener mErrorListener = new IMediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(IMediaPlayer mp, int what, int extra) {
            if (mOnErrorListener != null) {
                mOnErrorListener.onError(what, extra);
            }
            return true;
        }
    };
    private IMediaPlayer.OnInfoListener mInfoListener = new IMediaPlayer.OnInfoListener() {
        @Override
        public boolean onInfo(IMediaPlayer mp, int what, int extra) {
            if (mOnInfoListener != null) {
                mOnInfoListener.onInfo(what, extra);
            }
            return true;
        }
    };


    public OnPreparedListener getOnPreparedListener() {
        return mOnPreparedListener;
    }

    public void setOnPreparedListener(OnPreparedListener onPreparedListener) {
        mOnPreparedListener = onPreparedListener;
    }

    public OnCompletionListener getOnCompletionListener() {
        return mOnCompletionListener;
    }

    public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
        mOnCompletionListener = onCompletionListener;
    }

    public OnBufferingUpdateListener getOnBufferingUpdateListener() {
        return mOnBufferingUpdateListener;
    }

    public void setOnBufferingUpdateListener(OnBufferingUpdateListener onBufferingUpdateListener) {
        mOnBufferingUpdateListener = onBufferingUpdateListener;
    }

    public OnSeekCompleteListener getOnSeekCompleteListener() {
        return mOnSeekCompleteListener;
    }

    public void setOnSeekCompleteListener(OnSeekCompleteListener onSeekCompleteListener) {
        mOnSeekCompleteListener = onSeekCompleteListener;
    }

    public OnVideoSizeChangedListener getOnVideoSizeChangedListener() {
        return mOnVideoSizeChangedListener;
    }

    public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener onVideoSizeChangedListener) {
        mOnVideoSizeChangedListener = onVideoSizeChangedListener;
    }

    public OnErrorListener getOnErrorListener() {
        return mOnErrorListener;
    }

    public void setOnErrorListener(OnErrorListener onErrorListener) {
        mOnErrorListener = onErrorListener;
    }

    public OnInfoListener getOnInfoListener() {
        return mOnInfoListener;
    }

    public void setOnInfoListener(OnInfoListener onInfoListener) {
        mOnInfoListener = onInfoListener;
    }
}
